﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;

namespace Holidays {

	public static class DateTimeExtensions {

		/// <summary>
		/// Extension method returning the Utc time of the given DateTime
		/// </summary>
		/// <param name="dt"></param>
		/// <returns></returns>
		/// <remarks>
		/// If the given DateTime is of the Unspecified kind, the same DateTime will be returned, but now of the Utc kind.
		/// Use this before storing and when fetching dates with Entity Framework to keep only Utc dates in the database.
		/// </remarks>
		public static DateTime ToUtc(this DateTime dt) {
			if (dt.Kind == DateTimeKind.Unspecified) {
				return new DateTime(dt.Ticks, DateTimeKind.Utc);
			}
			else if (dt.Kind != DateTimeKind.Utc) {
				return TimeZoneInfo.ConvertTimeToUtc(dt);
			}
			return dt;
		}

		/// <summary>
		/// Extension method that returns an array of holiday dates for the year of the given date.
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public static DateTime[] Holidays(this DateTime date) {
			throw new NotImplementedException();
			return DateHelper.GetHolidays(date.Year);
		}

		/// <summary>
		/// Extension method for getting the date of the first day of the given type for the month of the given date.
		/// </summary>
		/// <param name="date"></param>
		/// <param name="dow"></param>
		/// <returns></returns>
		public static DateTime FirstInMonth(this DateTime date, DayOfWeek dow) {
			return DateHelper.GetFirstInMonth(date.Year, date.Month, dow);
		}

		/// <summary>
		/// Extension method for getting the date of the last day of the given type for the month of the given date.
		/// </summary>
		/// <param name="date"></param>
		/// <param name="dow"></param>
		/// <returns></returns>
		public static DateTime LastInMonth(this DateTime date, DayOfWeek dow) {
			return DateHelper.GetLastInMonth(date.Year, date.Month, dow);
		}

		/// <summary>
		/// Extension method that returns true if the given date is a work-day.
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public static Boolean IsWorkday(this DateTime date) {
			return !date.IsWeekend() && !date.IsHoliday();
		}

		/// <summary>
		/// Extension method that returns true if the given date is a weekend day.
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public static Boolean IsWeekend(this DateTime date) {
			String currentCulture = CultureInfo.CurrentCulture.Name;
			return CalculatorFactory.GetCalculator(currentCulture).IsWeekend(date);
		}

		/// <summary>
		/// Extension method that returns true if the given date is a holiday.
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public static Boolean IsHoliday(this DateTime date) {
			String currentCulture = CultureInfo.CurrentCulture.Name;
			return CalculatorFactory.GetCalculator(currentCulture).IsHoliday(date);
		}
	}
}